/*
 * DCE400服务系统 -- 后端服务接口 -- 数据访问层 -- 工单数据访问
 * 包括：
 */
package dao

import (
	"errors"
	"gitee.com/baal1990/gitee.com/baal1990/cmd/server_attence/app/entity"
	"gitee.com/baal1990/gitee.com/baal1990/cmd/server_attence/app/global"
	"gitee.com/baal1990/gitee.com/baal1990/pkg/db"
	"gitee.com/baal1990/gitee.com/baal1990/pkg/util"
	"go.uber.org/zap"
	"time"
)

//********************************************
//Func  ：查询数据库：加班列表分页查询。
//Method：startDate 格式 yyyy-mm-dd hh:MM:dd
//Usage ：
//********************************************
func QueryVacationList(page, pageSize, vacationType, status int,
	startDate, endDate string, applicantId, deptId int64) (int64, []*entity.VacationInfo, error) {

	offset := (page - 1) * pageSize
	session := db.Session().Table("vacation")
	defer session.Close()

	if pageSize > 0 {
		session.Limit(pageSize, offset)
	}
	if vacationType > entity.EVacationType_Unknow && vacationType <= entity.EVacationType_Other {
		session = session.And("vacation.type=?", vacationType)
	}
	if status > entity.EVacationStatus_Draft && status <= entity.EVacationStatus_Pass {
		session = session.And("vacation.status=?", status)
	}
	if startDate != "" {
		dtLayout := "2006-01-02 15:04:05" //严格按照time包要求的格式
		loc := db.TZLocation()            //转换日期的时区
		start, serr := time.ParseInLocation(dtLayout, startDate, loc)
		if serr == nil {
			session = session.And("vacation.start_date >= ?", start.Format("2006-01-02 15:04:05"))
		}
	}
	if endDate != "" {
		dtLayout := "2006-01-02 15:04:05" //严格按照time包要求的格式
		loc := db.TZLocation()            //转换日期的时区
		end, eerr := time.ParseInLocation(dtLayout, endDate, loc)
		if eerr == nil {
			session = session.And("vacation.end_date <= ?", end.Format("2006-01-02 15:04:05"))
		}
	}
	if applicantId > 0 {
		session = session.And("vacation.applicant_id = ?", applicantId)
	}
	if deptId > 0 {
		session = session.And("vacation.dept_id = ?", deptId)
	}

	vacationList := []*entity.VacationInfo{}
	total, err := session.Omit("applicant_name,approver_name,dept_name,duration_day,apply_type,apply_status").
		Cols("vacation.id,vacation.applicant_id,vacation.dept_id,reason,approver_id,start_date,"+
			"end_date,duration,vacation.create_at,approve_at,vacation.type,vacation.status,note,"+
			"department2.dept_id,department2.dept_name").
		Join("INNER", "department2", "vacation.dept_id = department2.dept_id").
		FindAndCount(&vacationList)
	if err != nil {
		return 0, nil, err
	}

	employeeMap := GetAllEmployeeMap()

	for _, v := range vacationList {
		v.DurationDay = v.Duration
		v.ApplyType = VacationTypeString(v.Type)
		v.ApplyStatus = OvertimeStatusString(v.Status) //这个请假和加班是通用的
		if employeeMap != nil {
			user, has := employeeMap[v.ApproverId]
			if has {
				v.ApproverName = user.Name
			}

			user, has = employeeMap[v.ApplicantId]
			if has {
				v.ApplicantName = user.Name
			}
		}
	}

	return total, vacationList, nil
}

//********************************************
//Func  ：查询数据库：指定加班的详情
//Method：GET
//Usage ：
//********************************************
func QueryVacationDetail(Id int64) (*entity.Vacation, error) {
	session := db.Session().Table("vacation")
	defer session.Close()

	var vacation entity.Vacation
	has, err := session.Where("id=?", Id).Get(&vacation)
	if err != nil || has == false {
		return nil, err
	}
	return &vacation, nil
}

//提供连表查询更详细的内容
func QueryVacationInfo(Id int64) (*entity.VacationInfo, error) {
	var vacationInfo entity.VacationInfo

	session := db.Session().Table("vacation")
	defer session.Close()

	has, err := db.Session().Table("vacation").Where("id=?", Id).
		Cols("vacation.id,vacation.applicant_id,vacation.dept_id,reason,approver_id,start_date,"+
			"end_date,duration,vacation.create_at,approve_at,vacation.type,vacation.status,note,"+
			"department2.dept_id,department2.dept_name").
		Join("INNER", "department2", "vacation.dept_id = department2.dept_id").
		Get(&vacationInfo)

	if err != nil || has == false {
		return nil, err
	}

	applicant, err := QueryEmployeeDetail("", vacationInfo.ApplicantId)
	if err == nil && applicant != nil {
		vacationInfo.ApplicantName = applicant.Name
	} else {
		global.Log.Info("QueryVacationInfo no found applicant: ", zap.Any("ApplicantId:", vacationInfo.ApplicantId))
	}

	approver, err := QueryEmployeeDetail("", vacationInfo.ApproverId)
	if err == nil && approver != nil {
		vacationInfo.ApproverName = approver.Name
	} else {
		global.Log.Info("QueryVacationInfo no found approver: ", zap.Any("ApproverId:", vacationInfo.ApproverId))
	}
	vacationInfo.DurationDay = vacationInfo.Duration
	vacationInfo.ApplyType = VacationTypeString(vacationInfo.Type)
	vacationInfo.ApplyStatus = OvertimeStatusString(vacationInfo.Status) //这个请假和加班是通用的

	return &vacationInfo, nil
}

//********************************************
//Func  ：添加新假期
//Method：POST
//Usage ：
//********************************************
func InsertVacation(vacation entity.Vacation) (*entity.Vacation, error) {
	var err error

	vacation.CreateAt = time.Now()
	vacation.Status = entity.EOvertimeStatus_Send
	vacation.Id = util.GenSnowflakeInt64()
	global.Log.Info("InsertVacation: ", zap.Any("vacation:", vacation))

	session := db.Session().Table("vacation")
	defer session.Close()
	err = session.Begin()
	if err != nil {
		return nil, errors.New("db session begin failed.")
	}
	_, err = session.Insert(&vacation) //插入
	if err != nil {
		session.Rollback()
		return nil, err
	}
	err = session.Commit()
	if err != nil {
		return nil, err
	}
	return &vacation, nil
}

//********************************************
//Func  ：更新假期信息
//Method：POST
//Usage ：修改： 审批人ID、ApproveAt、Status。或者特殊的cols的内容
//********************************************
func UpdateVacation(vacation entity.Vacation, cols string) error {
	var err error
	if vacation.Id <= 0 {
		return errors.New("vacation id is none")
	}
	session := db.Session().Table("vacation")
	defer session.Close()
	err = session.Begin()
	if err != nil {
		return err
	}

	if cols == "" {
		cols = "approver_id,approve_at,status"
	}
	_, err = session.Where("id=?", vacation.Id).Cols(cols).Update(vacation)
	if err != nil {
		return err
	}
	err = session.Commit()
	return err
}

//********************************************
//Func  ：批量更新假期信息
//Method：POST
//Usage ：修改： 审批人ID、ApproveAt、Status。或者特殊的cols的内容
//********************************************
func UpdateVacationBatch(vacationList []entity.Vacation, cols string) error {
	var err error
	if len(vacationList) <= 0 {
		return errors.New("vacation id is none")
	}
	session := db.Session().Table("vacation")
	defer session.Close()
	err = session.Begin()
	if err != nil {
		return err
	}

	if cols == "" {
		cols = "approver_id,approve_at,status"
	}
	for _, vacation := range vacationList {
		_, err = session.Where("id=?", vacation.Id).Cols(cols).Update(vacation)
		if err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}

//********************************************
//Func  ：删除加班数据
//Method：DELETE
//Usage ：物理删
//********************************************
func DeleteVacation(vacationId int64) error {
	if vacationId <= 0 {
		return errors.New("vacation id is none")
	}

	session := db.Session().Table("vacation")
	defer session.Close()
	session.Begin()

	cnt, err := session.Where("id=?", vacationId).Delete(&entity.Vacation{})
	if err != nil {
		session.Rollback()
		return err
	}
	if cnt <= 0 {
		session.Rollback()
		return errors.New("remove 0 vacation")
	}
	err = session.Commit()
	return err
}
